<template>
  <el-container class="sign-main">
    <el-header class="header">
      <div class="title">在线签章</div>
      <div class="btns">
        <input id="excel-upload" type="file" style="display:none;" @change="uploadHandle" />
        <input id="seal-upload" type="file" style="display:none;" @change="uploadSealHandle" />
        <el-button type="danger" size="small" @click="beforeUpload">上传需要签名的PDF</el-button>
        <el-button type="danger" size="small" :disabled="showPDF" @click="keywordHandle">关键字盖章</el-button>
        <el-button
          type="danger"
          size="small"
          :disabled="showPDF"
          @click="finish"
          v-if="type !== 'ukey'"
        >完成签署(后台)</el-button>
        <el-button
          type="danger"
          size="small"
          :disabled="showPDF"
          @click="startSeal"
          v-if="type !== 'ukey'"
        >完成签署(模拟ukey)</el-button>
        <el-button
          type="danger"
          size="small"
          :disabled="showPDF"
          @click="startSeal"
          v-if="type === 'ukey'"
        >完成签署(ukey)</el-button>
      </div>
    </el-header>
    <el-container>
      <el-aside width="250px" class="aside">
        <div class="title">文件签署</div>
        <span>拖动 印章至想要加盖的位置</span>
        <div class="seal-img">
          <div class="seal-img-move" @click="beforeUploadSeal">
            <img v-if="sealimg" class="s-icon" draggable="true" @dragstart="move" :src="sealimg" />
            <div v-else>{{ type === 'ukey' ? '请插入ukey' : '上传签章' }}</div>
          </div>
        </div>
        <el-button
          type="danger"
          size="medium"
          name="xxxxx"
          v-if="sealimg"
          :disabled="showPDF"
          plain
          @click="pagingSeal.show = true"
        >点击加盖骑缝章</el-button>
      </el-aside>
      <el-main v-if="showPDF" class="main" v-loading="loading" :element-loading-text="loadingMsg">
        <embed class="lookpdf" :src="`${baseurl}/pdf/pdf/${domID}`" />
      </el-main>
      <el-main v-else class="main" v-loading="loading" :element-loading-text="loadingMsg">
        <div class="pdfs">
          <el-scrollbar style="height: 100%;" id="pdfsbody">
            <div
              class="pdf"
              :id="`pdf-${i}`"
              v-for="i in pages"
              :key="i"

            >
              {{ i }}
              <img class="pdf-img" :src="`${baseurl}/pdf/img/${domID}/${i}`" />
              <div class="seals"  @drop="drop($event, i)" @dragover="allowDrop">
                <nja-seal
                  v-for="seal in seals.filter(d => d.page === i)"
                  :x.sync="seal.x"
                  :y.sync="seal.y"
                  @del="del(seal)"
                  :src="sealimg"
                  :key="seal.id"
                ></nja-seal>
                <nja-seal
                  v-if="pagingSeal.show"
                  :isPaging="true"
                  :x.sync="pagingSeal.x"
                  :y.sync="pagingSeal.y"
                  :src="sealimg"
                  @del="pagingSeal.show = false"
                ></nja-seal>
              </div>
            </div>
          </el-scrollbar>
        </div>

        <div class="pre-pdfs">
          <el-scrollbar style="height: 100%;">
            <div
              class="pre-pdf"
              v-for="i in pages"
              :key="i"
              :class="{ iscurrent: current === i }"
              @click="move2page(i)"
            >
              <div class="pdf-num">{{ i }}</div>
              <img class="pdf-img" :src="`${baseurl}/pdf/img/${domID}/${i}`" />
            </div>
          </el-scrollbar>
        </div>
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
import NjaSeal from './Seal'
import axios from 'axios'
import { readUkey, decodeCert, signData } from './common/ukey.js'
export default {
  props: ['id', 'type'],
  components: {
    NjaSeal
  },
  data() {
    return {
      showPDF: false,
      hasPdf: false,
      loading: false,
      sealimg: '',
      loadingMsg: 'PDF处理中',
      usercert: '',
      pages: 0,
      domID: '',
      current: 1,
      baseurl: process.env.VUE_APP_SEAL_BASE_PATH,
      scrollState: true,
      pagingSeal: {
        show: false,
        x: 794 - 80,
        y: 1124 / 2 - 80
      },
      seals: []
    }
  },
  methods: {
    convert(x, y) {
      return {
        x: parseInt((x / 794) * 595),
        y: 842 - parseInt(((y + 165) / 1124) * 842)
      }
    },
    convertPage(x, y) {
      return {
        x: parseInt((x / 595) * 794) - 80,
        y: parseInt(((842 - y) / 842) * 1124 - 80)
      }
    },
    keywordHandle() {
      // 关键字盖章
      this.$prompt('请输入关键字', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputValidator(keyword) {
          return !!keyword
        },
        inputErrorMessage: '关键字必填'
      }).then(async ({ value }) => {
        let result = await this.loadRemoteData(`${this.baseurl}/pdf/getxy`, {
          id: this.domID,
          keyword: value
        })
        if (!result) {
          this.$message({
            message: '未找到关键字',
            type: 'error'
          })
          return
        }
        this.seals = result.map((d, i) => {
          let { x, y } = this.convertPage(d.centreX, d.centreY)
          return {
            id: i,
            x,
            y,
            page: d.page
          }
        })
      })
    },
    beforeUpload() {
      // 上传前
      document.getElementById('excel-upload').click()
    },
    async readUkeyHandle() {
      if (this.type !== 'ukey') {
        return
      }
      // 获取证书
      this.usercert = readUkey()
      // 解析证书
      let { serialNumber } = await decodeCert(
        `${this.baseurl}/cert/info`,
        this.usercert
      )
      if (!serialNumber) {
        this.$message({
          message: '读取ukey失败',
          type: 'error'
        })
        return
      }
      let result = await this.loadRemoteData(`${this.baseurl}/pdf/seal/img`, {
        serialNumber: serialNumber
      })
      if (!result) {
        this.$message({
          message: '读取ukey印章失败',
          type: 'error'
        })
        return
      }
      this.sealimg = 'data:image/png;base64,' + result
    },
    async beforeUploadSeal() {
      if (this.type === 'ukey') {
        // 读ukey
        this.readUkeyHandle()
        return
      }
      document.getElementById('seal-upload').click()
    },
    uploadSealHandle(obj) {
      // 上传
      let that = this
      // 2.如果没有选中文件则取消
      if (!obj.target.files) {
        return
      }
      // 3.获得选择的文件对象
      let file = obj.target.files[0]
      let reader = new FileReader()
      reader.onloadend = function () {
        // 把转换后的数据给id为base64Img的src属性
        console.log('图片数据：', reader.result)
        that.sealimg = reader.result
      }
      if (file) {
        reader.readAsDataURL(file)
      }
    },
    uploadHandle(obj) {
      // 上传
      // 2.如果没有选中文件则取消
      if (!obj.target.files) {
        return
      }
      this.loadingMsg = 'PDF处理中'
      this.loading = true
      // 3.获得选择的文件对象
      let file = obj.target.files[0]
      let formData = new FormData()
      formData.append('file', file)
      axios
        .post(`${this.baseurl}/pdf/upload`, formData, {
          headers: { 'Content-Type': 'multipart/form-data' }
        })
        .then((res) => {
          console.log(res)
          this.loading = false
          this.showPDF = false
          if (res.status === 200 && res.data.status === 0) {
            let { id, pages } = res.data.data
            this.domID = id
            this.pages = pages
            this.pagingSeal.show = false
            this.seals = []
            this.$router.replace({
              path: this.$route.path,
              query: { id: id, type: this.type }
            })
            document.getElementById('excel-upload').value = ''
            this.$message({
              message: '上传成功',
              type: 'success'
            })
          }
        })
        .catch((err) => {
          console.error(err)
          this.loading = false
          document.getElementById('excel-upload').value = ''
          this.$message({
            message: '上传失败',
            type: 'error'
          })
        })
    },
    loadRemoteData(url, params) {
      return this.$http
        .post(url, params)
        .then((res) => {
          if (res.status === 0) {
            return res.data
          } else {
            return false
          }
        })
        .catch((err) => {
          console.log(err)
          return false
        })
    },
    async signSeal(index, data) {
      let result = await this.loadRemoteData(`${this.baseurl}/pdf/sign`, {
        id: this.domID,
        index: index,
        base64SignedDate: data
      })
      if (!result) {
        this.loading = false
        this.$message({
          message: '签章失败',
          type: 'error'
        })
        return
      }
      // 签章
      this.signDataHandle(result)
    },
    async startSeal() {
      this.loadingMsg = '正在签章...'
      this.loading = true
      let cert
      if (this.type === 'ukey') {
        cert = this.usercert
      } else {
        // 模拟ukey
        cert = await this.loadRemoteData(`${this.baseurl}/pdf/mockCert`, {})
      }
      // 开始签章
      this.$http
        .postJson(`${this.baseurl}/pdf/startSeal`, {
          id: this.domID,
          cert: cert,
          sealStr: this.sealimg.replace('data:image/png;base64,', ''), // 图片
          seals: this.seals.map((d) => {
            let { x, y } = this.convert(d.x, d.y)
            return {
              page: d.page,
              x,
              y
            }
          }),
          paging: this.pagingSeal.show
            ? { y: this.convert(this.pagingSeal.x, this.pagingSeal.y).y }
            : null
        })
        .then(async (res) => {
          console.log('nja==> ', res)
          if (res.status !== 0) {
            return Promise.reject(new Error())
          }
          // 签章
          this.signDataHandle(res.data)
        })
        .catch((err) => {
          console.log(err)
          this.loading = false
          this.$message({
            message: `pdf签署失败`,
            type: 'error'
          })
        })
    },
    async signDataHandle(data) {
      // 签名处理
      if (data.complete) {
        // 结束
        this.showPDF = true
        this.loading = false
        this.$message({
          message: '签署成功',
          type: 'success'
        })
        return
      }
      // 继续
      let digest
      if (this.type === 'ukey') {
        digest = signData(data.digest, true)
      } else {
        digest = await this.loadRemoteData(`${this.baseurl}/pdf/mockSign`, {
          srcDara: data.digest
        })
      }
      this.signSeal(data.index, digest)
    },
    finish() {
      this.loadingMsg = '正在签章...'
      this.loading = true
      // 完成签章
      this.$http
        .postJson(`${this.baseurl}/pdf/finish`, {
          id: this.domID,
          sealStr: this.sealimg.replace('data:image/png;base64,', ''), // 图片
          seals: this.seals.map((d) => {
            let { x, y } = this.convert(d.x, d.y)
            return {
              page: d.page,
              x,
              y
            }
          }),
          paging: this.pagingSeal.show
            ? { y: this.convert(this.pagingSeal.x, this.pagingSeal.y).y }
            : null
        })
        .then((res) => {
          console.log('nja==> ', res)
          this.showPDF = true
          this.loading = false
          this.$message({
            message: '签署成功',
            type: 'success'
          })
        })
        .catch((err) => {
          console.log(err)
          this.loading = false
          this.$message({
            message: `pdf签署失败`,
            type: 'error'
          })
        })
    },
    move2page(page) {
      this.current = page
      this.scrollState = false
      document.getElementById(`pdf-${page}`).scrollIntoView({
        behavior: 'smooth',
        // block: 'nearest',
        block: 'start',
        inline: 'start'
      })

      this.$nextTick(() => {
        setTimeout(() => {
          this.scrollState = true
        }, 1000)
      })
    },
    loadData() {
      if (!this.id) {
        return
      }

      console.log('this.id', this.id, this.domID)
      this.$http
        .post(`${this.baseurl}/pdf/images`, { id: this.domID })
        .then((res) => {
          console.log('nja==> ', res)
          if (res.status === 0) {
            if (res.data.finish) {
              // 已完成
              this.showPDF = true
            } else {
              this.pages = res.data.pages
            }
          } else {
            this.$message({
              message: res.data || `文件ID:${this.domID}未找到`,
              type: 'error'
            })
          }
        })
        .catch((err) => {
          console.log(err)
          this.$message({
            message: err.data || `查询异常`,
            type: 'error'
          })
        })
    },
    del(item) {
      this.seals.splice(
        this.seals.findIndex((d) => d.id === item.id),
        1
      )
    },
    drop(ev, i) {
      let xy = JSON.parse(ev.dataTransfer.getData('Text'))
      this.seals.push({
        id: new Date().getTime(),
        page: i,
        x: ev.offsetX - xy.x,
        y: ev.offsetY - xy.y
      })
    },
    allowDrop(ev) {
      ev.preventDefault()
    },
    move(ev) {
      let x = ev.offsetX
      let y = ev.offsetY
      ev.dataTransfer.setData('Text', JSON.stringify({ x, y }))
    }
  },
  mounted() {
    this.domID = this.id
    this.loadData()
    this.readUkeyHandle()
    document.querySelectorAll('.el-scrollbar__view').forEach((d) => {
      if (d.parentNode.parentNode.id === 'pdfsbody') {
        d.parentNode.addEventListener('scroll', () => {
          if (this.scrollState) {
            this.current = parseInt(d.parentNode.scrollTop / 1153) + 1
          }
        })
      }
    })
  }
}
</script>

<style lang="scss" scoped>
.sign-main {
  background: #f2f2f2;
  height: 100vh;
  .header {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    background-color: #fff;
    box-shadow: 0 5px 5px 2px rgba(0, 0, 0, 0.1);
    border-top: 1px solid #e5e5e5;
    margin-bottom: 30px;
  }
  .aside {
    padding: 0 20px;
    text-align: center;
    border-right: 1px solid rgba(250, 250, 250, 0.5);
    font-size: 14px;
    color: #999;
    .title {
      height: 40px;
      font-size: 24px;
      color: #333;
      border-bottom: 1px solid #ccc;
    }
    .seal-img {
      padding: 10px;
      background-color: #fff;
      text-align: center;
      border-radius: 6px;
      margin-top: 20px;
      margin-bottom: 20px;
    }
  }
  .s-icon {
    width: 80%;
    max-width: 200px;
    cursor: move;
  }
  .seal-img-move {
    height: 160px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: transparent;
    position: relative;
    cursor: pointer;
  }
  .main {
    background-color: #323740;
    position: relative;
    text-align: center;
    overflow: hidden;
    padding: 0px;
    .lookpdf {
      width: 100%;
      height: calc(100vh - 90px);
    }
    ::v-deep .el-scrollbar__wrap {
      // 隐藏框架布局layout.vue中el-aside和el-main下面的横向滚动条
      overflow-x: hidden;
    }
    .pdfs {
      margin: 20px auto 24px;
      margin-bottom: 0px;
      overflow: auto;
      width: 794px;
      height: calc(100vh - 120px);
      .pdf {
        position: relative;
        width: 794px;
        height: 1124px;
        // height: 100%;
        // width:595.0====;height:842.0
        background-color: rgba(100,100,100,0.5);
        margin-bottom: 30px;
        .seals {
          top: 0px;
          left: 0px;
          position: absolute;
          width: 100%;
          height: 100%;
        }
      }
    }
    .pre-pdfs {
      position: absolute;
      right: 8px;
      top: 20px;
      overflow: auto;
      width: 115px;
      border-left: 10px solid #323740;
      background-color: #323740;
      height: calc(100vh - 120px);
      .pre-pdf {
        position: relative;
        width: 101px;
        height: 141px;
        margin-left: 5px;
        margin-top: 5px;
        background-color: rgba(100,100,100,0.5);
        margin-bottom: 25px;
        cursor: pointer;
      }
    }
    .pdf-img {
      position: absolute;
      left: 0px;
      top: 0px;
      width: 100%;
      height: 100%;
      object-fit:contain;
    }
    .pdf-num {
      position: absolute;
      font-size: 30px;
      font-weight: 700;
      color: rgba(0, 0, 0, 0.7);
      width: 100%;
      text-align: center;
      bottom: 10px;
      z-index: 99;
    }
  }
  .iscurrent {
    box-shadow: 0px 0px 5px 3px rgba($color: #f56c6c, $alpha: 0.8);
    .pdf-num {
      color: #f56c6c;
    }
  }
}
</style>
